package libs

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/md5"
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	mrand "math/rand"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
)

var ProductName = "EditToServer"
var Version = "1.0.0"
var TrialDays = 7

func PrintProductInfo() {
	fmt.Println("┌───────────────────────────────────────────────────────────────────────┐")
	fmt.Println("                                                                         ")
	fmt.Println("                        " + ProductName + " V" + Version + "             ")
	fmt.Println("                                                                         ")
	fmt.Println("    开发不易,请珍惜开发劳动成果,本工具为免费工具,订阅版无时间限制           ")
	fmt.Println("    Author QQ:2401036 Wechat:songlin20111026 Email:9rax.dev@gmail.com   ")
	fmt.Println("    更多原创工具与BUG反馈请前往  https://dev.z-y.site                      ")
	fmt.Println("                                                                         ")
	fmt.Println("└───────────────────────────────────────────────────────────────────────┘")

	if !ValidateLicense() {

	}
}

// 新增函数用于获取和保存首次运行时间
func getFirstRunTime() time.Time {
	configDir, err := os.UserConfigDir()
	if err != nil {
		return time.Now()
	}

	filePath := filepath.Join(configDir, ".edtts_firstrun")
	data, err := os.ReadFile(filePath)
	if err == nil {
		t, err := time.Parse(time.RFC3339, string(data))
		if err == nil {
			return t
		}
	}

	// 如果文件不存在或无法解析,则创建新的时间戳
	now := time.Now()
	os.WriteFile(filePath, []byte(now.Format(time.RFC3339)), 0600)
	return now
}

// 新增函数用于验证许可证
func ValidateLicense() bool {

	firstRunTime := getFirstRunTime()
	// 如果远程验证失败,检查是否在7天试用期内
	if time.Since(firstRunTime) <= time.Duration(TrialDays)*24*time.Hour {
		return true
	}

	if IsValidLocalLicense() {
		return true
	}

	// 尝试远程验证
	valid, err := remoteValidate(GetMachineID(), firstRunTime, AuthConfig.Key)
	if err == nil && valid {
		return true
	}

	// 超过TrialDays则提示订阅
	if time.Since(firstRunTime) > time.Duration(TrialDays)*24*time.Hour {
		fmt.Println("温馨提示:未订阅版本可以每次使用十分钟")
		go func() {
			time.Sleep(10 * time.Minute)
			fmt.Println("温馨提示:10分钟试用时间已到,程序即将退出。")
			os.Exit(1)
		}()

		return false
	}

	return true
}

// 远程验证函数
func remoteValidate(deviceID string, firstRunTime time.Time, localLicense string) (bool, error) {
	url := "https://api.example.com/validate" // 替换为实际的API地址
	data := map[string]string{
		"deviceID":     deviceID,
		"firstRunTime": firstRunTime.Format(time.RFC3339),
		"license":      localLicense,
		"version":      Version,
		"product":      ProductName,
	}
	jsonData, _ := json.Marshal(data)

	resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return false, err
	}
	defer resp.Body.Close()

	var result struct {
		Valid bool `json:"valid"`
	}
	err = json.NewDecoder(resp.Body).Decode(&result)
	if err != nil {
		return false, err
	}

	return result.Valid, nil
}

var AuthConfig AuthConfigStruct

type AuthConfigStruct struct {
	Key       string    `json:"key"`
	ExpiresAt time.Time `json:"expires_at"`
	MachineID string    `json:"machine_id"`
}

func GetMachineID() string {
	// 检测是否有分析或破解行为
	startTime := time.Now()

	hostname, _ := os.Hostname()
	interfaces, _ := net.Interfaces()
	var macs []string
	for _, i := range interfaces {
		if i.Flags&net.FlagUp != 0 && !strings.HasPrefix(i.Name, "lo") {
			addrs, err := i.Addrs()
			if err != nil {
				continue
			}
			for _, addr := range addrs {
				if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
					if ipnet.IP.To4() != nil {
						macs = append(macs, i.HardwareAddr.String())
						break
					}
				}
			}
		}
	}
	id := hostname + strings.Join(macs, "")
	hash := sha256.Sum256([]byte(id))

	endTime := time.Now()
	elapsedTime := endTime.Sub(startTime)

	// 如果执行时间超过预期，可能存在分析或破解行为
	if elapsedTime > 100*time.Millisecond {
		// 这里可以添加一些防护措施，比如记录日志或返回错误的机器ID
		return generateRandomString(16)
	}

	return fmt.Sprintf("%x", hash[:16]) // 返回前16字节作为机器ID
}

// 生成指定长度的随机字符串
func generateRandomString(length int) string {
	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	b := make([]byte, length)
	for i := range b {
		b[i] = charset[mrand.Intn(len(charset))]
	}
	return string(b)
}

func EncryptKey(key string) (string, error) {
	encryptionKey := []byte("your-32-byte-secret-here!!!!!!!!")
	block, err := aes.NewCipher(encryptionKey)
	if err != nil {
		return "", err
	}

	plaintext := []byte(key)
	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		return "", err
	}

	stream := cipher.NewCFBEncrypter(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

	return base64.StdEncoding.EncodeToString(ciphertext), nil
}

func DecryptKey(encryptedKey string) (string, error) {
	encryptionKey := []byte("your-32-byte-secret-here!!!!!!!!")
	ciphertext, err := base64.StdEncoding.DecodeString(encryptedKey)
	if err != nil {
		return "", err
	}

	block, err := aes.NewCipher(encryptionKey)
	if err != nil {
		return "", err
	}

	if len(ciphertext) < aes.BlockSize {
		return "", fmt.Errorf("ciphertext too short")
	}
	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]

	stream := cipher.NewCFBDecrypter(block, iv)
	stream.XORKeyStream(ciphertext, ciphertext)

	return string(ciphertext), nil
}

func IsValidLocalLicense() bool {

	if Config.LicenseKey == "" {
		fmt.Println("配置文件中未找到许可证密钥")
		return false
	}

	decryptedKey, err := DecryptKey(Config.LicenseKey)
	if err != nil {
		fmt.Println("解密许可证密钥失败:", err)
		return false
	}

	parts := strings.Split(decryptedKey, "|")
	if len(parts) != 3 {
		fmt.Println("许可证格式错误")
		return false
	}

	machineID := parts[0]
	expiresAt, err := time.Parse("2006-01-02", parts[1])
	if err != nil {
		fmt.Println("解析过期时间失败:", err)
		return false
	}

	if machineID != GetMachineID() {
		fmt.Println("机器ID不匹配")
		return false
	}

	if time.Now().After(expiresAt) {
		fmt.Println("license已过期")
		return false
	}

	AuthConfig.Key = Config.LicenseKey
	AuthConfig.ExpiresAt = expiresAt
	AuthConfig.MachineID = machineID

	return true
}

func DeleteLicenseFile() {
	err := os.Remove(".license")
	if err != nil {
		if !os.IsNotExist(err) {
			fmt.Println("删除.license文件失败:", err)
		}
	} else {
		fmt.Println(".license文件已成功删除")
	}

	AuthConfig = AuthConfigStruct{}
}

func SaveAuthConfig() {
	err := os.WriteFile(".license", []byte(AuthConfig.Key), 0644)
	if err != nil {
		fmt.Println("保存授权密钥失败:", err)
	}
}

// 实现与 PHP 中 md5(md5(str).md5(str)) 等效的函数
func GetDoubleMD5Hash(str string) string {
	md5First := getMD5Hash(str)
	md5Second := getMD5Hash(str)
	return getMD5Hash(md5First + md5Second)
}

// 计算单次 MD5 哈希的辅助函数
func getMD5Hash(text string) string {
	hasher := md5.New()
	hasher.Write([]byte(text))
	return hex.EncodeToString(hasher.Sum(nil))
}

// GenerateKey 根据deviceID和product生成hash key
func GenerateKey() string {
	// 合并deviceID和product
	combined := GetMachineID() + ProductName

	// 使用SHA-256生成hash
	hash := sha256.Sum256([]byte(combined))

	// 将hash转换为16进制字符串
	key := hex.EncodeToString(hash[:])

	// 返回生成的key
	return key
}
